﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Perceiveit.Xml.Tests.Concrete;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Perceiveit.Xml.Tests
{
    /// <summary>
    /// Summary description for UnitTest1
    /// </summary>
    [TestClass]
    public class XEntityTests
    {
        private static bool OutputToConsole = true;

        public XEntityTests()
        {
            OutputToConsole = true;
            //
            // TODO: Add constructor logic here
            //
        }

        public string GetSampleString()
        {
            return Properties.Resources.Sample;
        }

        public XDocument GetSampleDocument()
        {
            XDocument xdoc = XDocument.Parse(this.GetSampleString());

            return xdoc;
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod()]
        public void _01_RootEntity()
        {
            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);

            if (OutputToConsole)
            {
                Console.WriteLine("Document loaded");
                Console.WriteLine(root);
            }
        }

        [TestMethod()]
        public void _02_ReadRootAttributes()
        {
            System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);

            Assert.AreEqual(root.IntegerValue, 1, "Integer failed");
            Assert.AreEqual(root.StringValue, "This is a string", "String Failed");
            Assert.AreEqual(root.GuidValue, new Guid("{1DFC21E2-4970-4662-9827-B967C0ADC803}"), "Guid Failed");
            Assert.AreEqual(root.BoolValue, true, "Boolean failed");
            Assert.AreEqual(root.DbTypeValue, System.Data.DbType.AnsiString, "DbType enum failed");
            Assert.AreEqual(root.ByteValue, 4, "Byte Failed");
            Assert.AreEqual(root.CharValue, 'c', "Char Failed");
            Assert.AreEqual(root.DateValue, new DateTime(2009, 10, 10, 12, 00, 00), "DateTimeFailed");
            Assert.AreEqual(root.DecimalValue, 34.1234M, "Decimal Failed");
            Assert.AreEqual(root.DoubleValue, 2000, "Double Failed");
            Assert.AreEqual(root.FloatValue, 12.1234F, "Float Failed");
            Assert.AreEqual(root.ColorValue, System.Drawing.Color.FromArgb(255, 255, 255), "Color Failed");
            Assert.AreEqual(root.LongValue, 1234567890, "Long Failed");
            Assert.AreEqual(root.Point, new System.Drawing.Point(12, 14), "Point Failed");
            Assert.AreEqual(root.SByteValue, -2, "SByte Failed");
            Assert.AreEqual(root.ShortValue, 3356, "Short Failed");
            Assert.AreEqual(root.TimeSpanValue, new TimeSpan(0, 1, 2, 3), "Timespan failed");
            Assert.AreEqual(root.UIntValue, (uint)123456, "UInt failed");
            Assert.AreEqual(root.ULongValue, (ulong)12345687989, "ULong Failed");
            Assert.AreEqual(root.UriValue, new Uri("http://this.isatest.com/page/"), "Uri Failed");
            Assert.AreEqual(root.UShortValue, (ushort)100, "UShort Failed");
            sw.Stop();

            if (OutputToConsole)
            {
                this.TestContext.WriteLine("All properties were validated in: " + sw.Elapsed);
            }
        }

        [TestMethod()]
        public void _03_WriteRootAttributes()
        {
            Guid g = Guid.NewGuid();
            DateTime dt = new DateTime(2010, 10, 10, 10, 10, 10);
            System.Drawing.Point pt = new System.Drawing.Point(100, 100);
            TimeSpan ts = new TimeSpan(2, 4, 6);
            Uri uri = new Uri("http://www.perceiveit.co.uk");

            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);
            root.IntegerValue = -100;
            root.StringValue = "This is another string";
            root.GuidValue = g;
            root.BoolValue = false;
            root.DbTypeValue = System.Data.DbType.Currency;
            root.ByteValue = 10;
            root.CharValue = 'z';
            root.DateValue = dt;
            root.DecimalValue = -123.456M;
            root.DoubleValue = -4000;
            root.FloatValue = -2123F;
            root.ColorValue = System.Drawing.Color.Firebrick;
            root.LongValue = -1234567890;
            root.Point = pt;
            root.SByteValue = -100;
            root.ShortValue = -129;
            root.TimeSpanValue = ts;
            root.UIntValue = 1234;
            root.ULongValue = 24680;
            root.UriValue = uri;
            root.UShortValue = 123;

            string newxml = root.Document.ToString(SaveOptions.None);

            if (OutputToConsole)
                this.TestContext.WriteLine(newxml);

            System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
            doc = XDocument.Parse(newxml);

            root = new Root();
            root.Init(doc);
            Assert.AreEqual(root.IntegerValue, -100, "Integer failed");
            Assert.AreEqual(root.StringValue, "This is another string", "String Failed");
            Assert.AreEqual(root.GuidValue, g, "Guid Failed");
            Assert.AreEqual(root.BoolValue, false, "Boolean failed");
            Assert.AreEqual(root.DbTypeValue, System.Data.DbType.Currency, "DbType enum failed");
            Assert.AreEqual(root.ByteValue, 10, "Byte Failed");
            Assert.AreEqual(root.CharValue, 'z', "Char Failed");
            Assert.AreEqual(root.DateValue, dt, "DateTimeFailed");
            Assert.AreEqual(root.DecimalValue, -123.456M, "Decimal Failed");
            Assert.AreEqual(root.DoubleValue, -4000.0, "Double Failed");
            Assert.AreEqual(root.FloatValue, -2123.0F, "Float Failed");
            Assert.AreEqual(root.ColorValue, System.Drawing.Color.Firebrick, "Color Failed");
            Assert.AreEqual(root.LongValue, -1234567890, "Long Failed");
            Assert.AreEqual(root.Point, pt, "Point Failed");
            Assert.AreEqual(root.SByteValue, -100, "SByte Failed");
            Assert.AreEqual(root.ShortValue, -129, "Short Failed");
            Assert.AreEqual(root.TimeSpanValue, ts, "Timespan failed");
            Assert.AreEqual(root.UIntValue, (uint)1234, "UInt failed");
            Assert.AreEqual(root.ULongValue, (ulong)24680, "ULong Failed");
            Assert.AreEqual(root.UriValue, uri, "Uri Failed");
            Assert.AreEqual(root.UShortValue,(ushort)123, "UShort Failed");
            sw.Stop();

            if (OutputToConsole)
            {
                this.TestContext.WriteLine("All properties were validated in: " + sw.Elapsed);
            }
        }

        [TestMethod()]
        public void _04_WriteRootTextElement()
        {
            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);
            Assert.AreEqual(root.IconText, new Uri("xan://imageserver1/logo.png"), "Uri text failed");
            root.IconText = new Uri("http://www.perceiveit.co.uk");
            string newxml = root.Document.ToString();
            //this.TestContext.WriteLine(newxml);
            root = new Root();
            doc = XDocument.Parse(newxml);
            root.Init(doc);
            Assert.AreEqual(root.IconText, new Uri("http://www.perceiveit.co.uk"), "Modified Icon Uri is not equal");

            if (OutputToConsole)
            {
                this.TestContext.WriteLine("Modified Uri matched");
            }
        }

        [TestMethod()]
        public void _05_ReadComplexElement()
        {
            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);
            LocalString name = root.LocalName;
            Assert.IsNotNull(name, "Complex child failed");
            Assert.AreEqual(name.Invariant, "Invariant Name", "Complex child attribute failed");
            Assert.AreEqual(name.Localized, "Local Name", "Complex child text failed");

            if (OutputToConsole)
            {
                this.TestContext.WriteLine("Complex Child read completed with invariant :'{0}' and local:'{1}'", name.Invariant, name.Localized);
            }
        }

        [TestMethod()]
        public void _06_WriteComplexElementAttributes()
        {
            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);
            LocalString name = root.LocalName;
            Assert.IsNotNull(name, "Complex child failed");
            Assert.AreEqual(name.Invariant, "Invariant Name", "Complex child attribute failed");
            Assert.AreEqual(name.Localized, "Local Name", "Complex child text failed");
            name.Localized = "New Local Name";
            name.Invariant = "New Invariant Name";

            string newxml = root.Document.ToString();
            root = new Root();
            root.Init(XDocument.Parse(newxml));
            name = root.LocalName;
            Assert.IsNotNull(name, "Complex child failed");
            Assert.AreEqual(name.Invariant, "New Invariant Name", "Complex child attribute failed");
            Assert.AreEqual(name.Localized, "New Local Name", "Complex child text failed");

            if (OutputToConsole)
            {
                this.TestContext.WriteLine("{0}",newxml);
                this.TestContext.WriteLine("Complex Child value writes completed with invariant :'{0}' and local:'{1}'", name.Invariant, name.Localized);
            }
        }

        [TestMethod()]
        public void _07_WriteComplexElementValue()
        {

            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);
            LocalString orig = root.LocalName;

            //create a new local string and assign it to the property
            LocalString name = new LocalString();
            name.Localized = "New Local Name";
            name.Invariant = "New Invariant Name";

            root.LocalName = name;

            //now convert to string and back to ensure we are a clean object
            //and check the values
            string newxml = root.Document.ToString();
            root = new Root();
            root.Init(XDocument.Parse(newxml));
            name = root.LocalName;
            Assert.IsNotNull(name, "Complex child failed");
            Assert.AreEqual(name.Invariant, "New Invariant Name", "Complex child attribute failed");
            Assert.AreEqual(name.Localized, "New Local Name", "Complex child text failed");

            Assert.AreEqual(orig.Invariant, "Invariant Name", "Retention of original values failed");
            Assert.AreEqual(orig.Localized, "Local Name", "Retention of original values failed");

            if (OutputToConsole)
            {
                this.TestContext.WriteLine("{0}",newxml);
                this.TestContext.WriteLine("");
                this.TestContext.WriteLine(orig.ToString());
                this.TestContext.WriteLine("Complex Child value writes completed with invariant :'{0}' and local:'{1}'", name.Invariant, name.Localized);
            }
        }


        [TestMethod()]
        public void _08_WriteComplexElementAsNull()
        {
            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);
            LocalString orig = root.LocalName;

            //assign null to the property

            root.LocalName = null;

            //now convert to string and back to ensure we are a clean object
            //and check the values
            string newxml = root.Document.ToString();
            root = new Root();
            root.Init(XDocument.Parse(newxml));
            Assert.IsNull(root.LocalName, "Complex child to null failed");

            Assert.AreEqual(orig.Invariant, "Invariant Name", "Retention of original values failed");
            Assert.AreEqual(orig.Localized, "Local Name", "Retention of original values failed");

            if (OutputToConsole)
            {
                this.TestContext.WriteLine("{0}",newxml);
                this.TestContext.WriteLine("");
                this.TestContext.WriteLine(orig.ToString());
                this.TestContext.WriteLine("Complex Child value writes to null completed");
            }
        }

        [TestMethod()]
        public void _09_SimpleChildList()
        {
            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);

            XList<SimpleChild> children = root.SimpleChildren;
            Assert.AreEqual(8, children.Count, "The number of child enities does not match");
            SimpleChild child = children[0];
            Assert.AreEqual(4, child.ID, "The ID of the first simple child does not match");
            Assert.AreEqual("Edit Library Properties", child.Value, "The Value of the first simple child does not match");
            child = children[7];//last item
            Assert.AreEqual(11, child.ID, "The ID of the last simple child does not match");
            Assert.AreEqual("View Library Map", child.Value, "The Value of the last simple child does not match");

            if (OutputToConsole)
            {
                this.TestContext.WriteLine("Simple child list validated");
            }
        }

        [TestMethod()]
        public void _10_WriteSimpleChildList()
        {
            XDocument doc = GetSampleDocument();
            Root root = new Root();
            root.Init(doc);

            XList<SimpleChild> children = root.SimpleChildren;
            Assert.AreEqual(8, children.Count, "The number of child enities does not match");

            SimpleChild child = new SimpleChild();
            child.ID = 20;
            child.Value = "This is a new value";
            children.Add(child);
            Assert.AreEqual(9, children.Count, "The number of child enities does not match after adding one");

            string xml = root.Document.ToString();

            if (OutputToConsole)
                this.TestContext.WriteLine("After Adding a simple child:\r\n{0}",xml);

            root = new Root();
            doc = XDocument.Parse(xml);
            root.Init(doc);
            children = root.SimpleChildren;
            Assert.AreEqual(9, children.Count, "The number of child enities does not match after adding one");
            child = children[8];//new last item
            Assert.AreEqual(20, child.ID, "The ID of the new added simple child does not match");
            Assert.AreEqual("This is a new value", child.Value, "The Value of the new added simple child does not match");

            child = new SimpleChild();
            child.ID = 21;
            child.Value = "Inserted value";
            root.SimpleChildren.Insert(4, child);
            Assert.AreEqual(10, root.SimpleChildren.Count, "The number of items after an insert and removal does not match");

            xml = root.Document.ToString();

            if (OutputToConsole)
                this.TestContext.WriteLine("After Inserting a simple child:\r\n{0}", xml);

            root = new Root();
            doc = XDocument.Parse(xml);
            root.Init(doc);
            children = root.SimpleChildren;
            children.RemoveAt(8);
            Assert.AreEqual(9, children.Count, "The number of child enities does not match after adding one");

            child = children[8];
            Assert.AreEqual(20, child.ID, "The ID of the new added simple child does not match");
            Assert.AreEqual("This is a new value", child.Value, "The Value of the new added simple child does not match");

            xml = root.Document.ToString();

            if (OutputToConsole)
                this.TestContext.WriteLine("After Inserting a simple child:\r\n{0}", xml);

            root = new Root();
            doc = XDocument.Parse(xml);
            root.Init(doc);
            children = root.SimpleChildren;

            Assert.AreEqual(9, children.Count, "The number of child enities does not match after adding one");
            child = children[4];//new last item
            Assert.AreEqual(21, child.ID, "The ID of the new added simple child does not match");
            Assert.AreEqual("Inserted value", child.Value, "The Value of the new added simple child does not match");

            child = children[8];
            Assert.AreEqual(20, child.ID, "The ID of the new added simple child does not match");
            Assert.AreEqual("This is a new value", child.Value, "The Value of the new added simple child does not match");

        }

        [TestMethod()]
        public void _11_EnumerateSimpleListTest()
        {

            Root root = new Root();
            XDocument doc = this.GetSampleDocument();
            root.Init(doc);
            XList<SimpleChild> children = root.SimpleChildren;
            int[] ids = new int[] { 4, 5, 6, 7, 8, 9, 10, 11 };
            int index = 0;

            foreach (SimpleChild child in children)
            {
                Assert.AreEqual(ids[index], child.ID, "The id of child at index '" + index.ToString() + "' was not the expected value");
                index++;
            }

            Assert.AreEqual(ids.Length, index, "Did not enumerate over all the items in the collection");
            Assert.AreEqual(children.Count, index, "Did not enumerate over all the items in the collection");
        }

        [TestMethod()]
        public void _12_CheckEnumerationAddNotificationTest()
        {
            Root root = new Root();
            XDocument doc = this.GetSampleDocument();
            root.Init(doc);
            XList<SimpleChild> children = root.SimpleChildren;
            int[] ids = new int[] { 4, 5, 6, 7, 8, 9, 10, 11 };
            int index = 0;

            try
            {
                index = 0;

                foreach (SimpleChild child in children)
                {
                    Assert.AreEqual(ids[index], child.ID, "The id of child at index '" + index.ToString() + "' was not the expected value");
                    if (index == 4)
                    {
                        //This should throw an invalid operation exception
                        //when the enumerator goes around again
                        SimpleChild toadd = new SimpleChild();
                        toadd.ID = 14;
                        children.Add(toadd);
                    }
                    index++;
                }
                //if we get to the end then we are in an error state
                throw new Exception("Didn't throw an exception when the collection was changed");
            }
            catch (InvalidOperationException)
            {
                //this is expected
            }
        }

        [TestMethod()]
        public void _13_CheckEnumerationRemoveNotificationTest()
        {
            Root root = new Root();
            XDocument doc = this.GetSampleDocument();
            root.Init(doc);
            XList<SimpleChild> children = root.SimpleChildren;
            int[] ids = new int[] { 4, 5, 6, 7, 8, 9, 10, 11 };
            int index = 0;

            try
            {
                index = 0;

                foreach (SimpleChild child in children)
                {
                    Assert.AreEqual(ids[index], child.ID, "The id of child at index '" + index.ToString() + "' was not the expected value");
                    if (index == 4)
                    {
                        //This should throw an invalid operation exception
                        //when the enumerator goes around again
                        children.RemoveAt(index);
                    }
                    index++;
                }
                //if we get to the end then we are in an error state
                throw new Exception("Didn't throw an exception when the collection was changed");
            }
            catch (InvalidOperationException)
            {
                //this is expected
            }
        }

        [TestMethod()]
        public void _14_CheckEnumerationSetNotificationTest()
        {
            Root root = new Root();
            XDocument doc = this.GetSampleDocument();
            root.Init(doc);
            XList<SimpleChild> children = root.SimpleChildren;
            int[] ids = new int[] { 4, 5, 6, 7, 8, 9, 10, 11 };
            int index = 0;

            try
            {
                index = 0;

                foreach (SimpleChild child in children)
                {
                    Assert.AreEqual(ids[index], child.ID, "The id of child at index '" + index.ToString() + "' was not the expected value");
                    if (index == 4)
                    {
                        //This should throw an invalid operation exception
                        //when the enumerator goes around again
                        SimpleChild toadd = new SimpleChild();
                        toadd.ID = 14;
                        children[index] = toadd;
                    }
                    index++;
                }
                //if we get to the end then we are in an error state
                throw new Exception("Didn't throw an exception when the collection was changed");
            }
            catch (InvalidOperationException)
            {
                //this is expected
            }
        }

        //TODO: Need to check the created of a new collection and assign to the property 
        //make sure it is all replaced, and the new elements are added to the xml properly

        [TestMethod()]
        public void _15_ComplexKeyedListLoad()
        {
            Root r = new Root();
            XDocument doc = this.GetSampleDocument();
            r.Init(doc);

            ComplexChildDictionary dict = r.Complex;
            Assert.AreEqual(dict.Count, 2);
        }

        [TestMethod()]
        public void _16_ComplexKeyedListItemTest()
        {
            Root r = new Root();
            XDocument doc = this.GetSampleDocument();
            r.Init(doc);

            ComplexChildDictionary dict = r.Complex;
            Assert.AreEqual(dict.Count, 2);
            ComplexChild child = dict[100];
            Assert.IsNotNull(child);
            Assert.AreEqual(1, child.Index);
            child = dict[101];
            Assert.IsNotNull(child);
            Assert.AreEqual(2, child.Index);

        }

        [TestMethod()]
        public void _17_ComplexKeyedListEnumerator()
        {
            Root r = new Root();
            XDocument doc = this.GetSampleDocument();
            r.Init(doc);

            ComplexChildDictionary dict = r.Complex;
            int index = 0;
            foreach (ComplexChild child in dict)
            {
                if (index == 0)
                {
                    Assert.AreEqual(1, child.Index);
                    Assert.AreEqual(100, child.ID);
                }
                else if (index == 1)
                {
                    Assert.AreEqual(2, child.Index);
                    Assert.AreEqual(101, child.ID);
                }
                else
                    throw new ArgumentOutOfRangeException("Gone past the end");
                index++;
            }

            Assert.AreEqual(index, 2, "Did not enumerate over all the items in the collection");
        }

        [TestMethod()]
        public void _18_ComplexKeyedListAddTest()
        {
            Root r = new Root();
            XDocument doc = this.GetSampleDocument();
            r.Init(doc);

            ComplexChildDictionary dict = r.Complex;

            ComplexChild newchild = new ComplexChild();
            newchild.ID = 102;
            newchild.Date = DateTime.Now;
            newchild.Description = new LocalString();
            
            newchild.Description.Localized = "Local new child";
            newchild.Description.Invariant = "Invariant new child";
            

            dict.Add(newchild);
            Assert.AreEqual(3, dict.Count);

            string xml = r.Document.ToString();

            if (OutputToConsole)
                Console.WriteLine(xml);

            
            r = new Root();
            doc = XDocument.Parse(xml);
            r.Init(doc);

            dict = r.Complex;
            Assert.AreEqual(3, dict.Count);
            newchild = dict[102];
            Assert.IsNotNull(newchild);
            Assert.AreEqual(newchild.ID, 102);
            Assert.IsNotNull(newchild.Description);
            Assert.AreEqual(newchild.Description.Localized, "Local new child");
            Console.WriteLine("Add complex to keyed collection complete");

        }

        [TestMethod()]
        public void _19_ComplexKeyedListRemoveTest()
        {
            Root r = new Root();
            XDocument doc = this.GetSampleDocument();
            r.Init(doc);

            ComplexChildDictionary dict = r.Complex;
            ComplexChild child = dict[101];
            dict.Remove(101);
            Assert.AreEqual(1, dict.Count);
            Assert.IsNull(dict[101]);

            string xml = r.Document.ToString();

            if (OutputToConsole)
                Console.WriteLine(xml);

            r = new Root();
            doc = XDocument.Parse(xml);
            r.Init(doc);

            Assert.AreEqual(1, r.Complex.Count);
            Assert.IsNotNull(r.Complex[100]);
            Assert.IsNull(r.Complex[101]);

            //Check the child extracted is still ok

            Assert.AreEqual(child.Index, 2);
            Assert.AreEqual(child.Description.Localized, "Local second item description");

            xml = child.ToString();

            if(OutputToConsole)
                Console.WriteLine(xml);
        }

        [TestMethod()]
        public void _20_ComplexKeyedListAddDuplicateTest()
        {
            XDocument doc = this.GetSampleDocument();
            Root r = new Root();
            r.Init(doc);
            ComplexChild child = new ComplexChild();
            child.ID = 101;//this should be a duplicate key
            child.Name = new LocalString();
            child.Name.Localized = "Local name";
            child.Name.Invariant = "Invariant";

            try
            {
                r.Complex.Add(child);
                throw new InvalidOperationException("No argument exception was thrown for a duplicate key");
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine("Sinking exception '" + ex.Message + "' because it was expected");
            }
            Assert.AreEqual(2, r.Complex.Count, "The item has not been added");
        }

        [TestMethod()]
        public void _21_NewRootNameAndContents()
        {
            Root r = new Root();
            r.BoolValue = true;
            r.IntegerValue = -1000;
            r.Point = new System.Drawing.Point(100, 120);
            r.LocalName = new LocalString();
            r.LocalName.Localized = "Local name";
            r.LocalName.Invariant = "Invariant";

            SimpleChild child = new SimpleChild();
            child.ID = 100;
            child.Value = "Simple child 100";
            r.SimpleChildren.Add(child);
            child = new SimpleChild();
            child.ID = 101;
            child.Value = "Simple child 101";
            r.SimpleChildren.Add(child);

            ComplexChild complex = new ComplexChild();
            complex.ID = 200;
            complex.Index = 0;
            complex.Name = new LocalString();
            complex.Name.Invariant = "Complex invariant";
            r.Complex = new ComplexChildDictionary();
            r.Complex.Add(complex);


            string xml;

            using (System.IO.StringWriter sw = new System.IO.StringWriter())
            {
                r.Document.Save(sw);
                sw.Flush();
                xml = sw.GetStringBuilder().ToString();
            }

            if (OutputToConsole)
                Console.WriteLine(xml);

            XDocument doc = XDocument.Parse(xml);
            r = new Root();
            r.Init(doc);

            Assert.AreEqual(true, r.BoolValue);
            Assert.AreEqual(-1000, r.IntegerValue);
            Assert.AreEqual(new System.Drawing.Point(100, 120), r.Point);
            Assert.AreEqual("Local name", r.LocalName.Localized);
            Assert.AreEqual("Invariant", r.LocalName.Invariant);

            //Assert.AreEqual(2, r.SimpleChildren.Count);
            Assert.AreEqual(100, r.SimpleChildren[0].ID);
            Assert.AreEqual("Simple child 100", r.SimpleChildren[0].Value);
            Assert.AreEqual(101, r.SimpleChildren[1].ID);
            Assert.AreEqual("Simple child 101",r.SimpleChildren[1].Value);

            Assert.AreEqual(1, r.Complex.Count);
            Assert.IsNotNull(r.Complex[200]);
            Assert.AreEqual("Complex invariant", r.Complex[200].Name.Invariant);

            if (OutputToConsole)
                Console.WriteLine("All new properties validated");
        }


        [TestMethod()]
        public void _22_DefaultInnerCollection()
        {
            XDocument doc = this.GetSampleDocument();
            Root r = new Root();
            r.Init(doc);

            DefaultListWrapper wrapper = r.DefaultListWrapper;
            Assert.IsNotNull(wrapper);

            //Makes sure we have some items
            Assert.IsFalse(wrapper.Count == 0);
            TestContext.WriteLine("Total item wrapper count is {0}", wrapper.Count);

            foreach (DefaultInnerType inner in wrapper)
            {
                if(inner is InnerType1)
                {
                    InnerType1 t1 = inner as InnerType1;
                    TestContext.WriteLine("Inner item  type 1 has id '{0}' and description : {1}", t1.ID, t1.Description);
                }
                else if (inner is InnerType2)
                {
                    InnerType2 t2 = inner as InnerType2;
                    TestContext.WriteLine("Inner item  type 2 has name '{0}' and description : {1}", t2.Name, t2.Description);
                }

            }
        }
    }
}
